//////////////////////////////////////////////////////////////////////////

#ifndef _MENUSCREEN_H_
#include "menuscreen.h"
#endif

//////////////////////////////////////////////////////////////////////////

#ifndef _MAINMENU_H_
#include "mainmenu.h"
#endif

#ifndef _SETTINGSMENU_H_
#include "settingsmenu.h"
#endif

#ifndef _CONNECTMENU_H_
#include "connectmenu.h"
#endif

#ifndef _CREATEMENU_H_
#include "createmenu.h"
#endif

#ifndef _INPUT_H_
#include "input.h"
#endif

#ifndef _TEXTSURFACE_H_
#include "textsurface.h"
#endif

#ifndef _COLORS_H_
#include "colors.h"
#endif

#ifndef _FONTS_H_
#include "fonts.h"
#endif

#ifndef _THEME_H_
#include "theme.h"
#endif

#ifndef _GUI_H_
#include "gui.h"
#endif

#ifndef _TIMER_H_
#include "timer.h"
#endif

#ifndef _SETTINGS_H_
#include "settings.h"
#endif
       
#ifndef _IMAGESURFACE_H_
#include "imagesurface.h"
#endif

#include <string>
#include <SDL\SDL_ttf.h>
#include <SDL\SDL.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <fstream>
#include <stdio.h>
#include <SDL_mixer.h>
//////////////////////////////////////////////////////////////////////////


GUI_MenuScreen::GUI_MenuScreen(GUI *_gui) : 
    m_GUI(_gui)
{
    m_ActiveMenu = Main;
    m_Layers.resize(LayerCount);
    m_Layers[Main] = new GUI_MainMenu();
    m_Layers[Settings] = new GUI_SettingsMenu();
    m_Layers[Connect] = new GUI_ConnectMenu();
    m_Layers[Create] = new GUI_CreateMenu();
    m_CurrentMapSelected = 0;

    m_NeedRepaint = true;

    std::ifstream FileStream(".\\maps");
    while (!FileStream.eof())
    {
        std::string MapName;
        getline(FileStream, MapName);
        if (MapName.size()>0)
            m_MapNames.push_back(MapName);
    }

    m_MenuBack =  new GUI_ImageSurface(GUI_Images::Background);       
    Mix_PlayMusic(GUI_Theme::GetMusic(GUI_Sounds::Menu), -1);

    AddEventToObserve(Observer::KEY_INPUT_CHANGE);
    AddEventToObserve(Observer::MOUSE_POSITION_CHANGE);
}


//////////////////////////////////////////////////////////////////////////


GUI_MenuScreen::~GUI_MenuScreen()
{
    Mix_HaltMusic();
    for (int i = 0; i < m_Layers.size(); ++i)
        delete m_Layers[i];
    delete m_MenuBack;
}


//////////////////////////////////////////////////////////////////////////


void GUI_MenuScreen::Render(SDL_Surface *_mainSurface)
{
    if(SDL_MUSTLOCK(_mainSurface)) 
    {
        if(SDL_LockSurface(_mainSurface) < 0) return;
    }

    SDL_Color back = GUI_Theme::Color(GUI_Colors::SplashBackground);
    
    if (m_NeedRepaint)
    {
        SDL_FillRect(_mainSurface, &_mainSurface->clip_rect, SDL_MapRGB(_mainSurface->format, back.r, back.g, back.b));
        m_MenuBack->Blt(_mainSurface, 0.5, 0.5);
    }
    m_Layers[m_ActiveMenu]->Render(_mainSurface, m_NeedRepaint);


    if(SDL_MUSTLOCK(_mainSurface)) SDL_UnlockSurface(_mainSurface);
    SDL_Flip(_mainSurface); 
}


//////////////////////////////////////////////////////////////////////////


void GUI_MenuScreen::Resize()
{
    for (int i = 0; i < LayerCount; ++i)
        m_Layers[i]->Resize();
}


//////////////////////////////////////////////////////////////////////////


void GUI_MenuScreen::ProcessInputResult(int _result)
{
    static int ScreenMode = 0;
    static bool FullscreenMode = false;
    char Buffer[256];
    SDL_Rect *Resolution;
    m_NeedRepaint = true;
    switch (m_ActiveMenu)
    {
    case Main:
        switch(_result)
        {
        case -2:
            m_NeedRepaint = false;
            break;
        case -1:
            break;
        case GUI_MainMenu::CreateGame:
            {
                m_ActiveMenu = Create;
                m_NeedRepaint = true;
                ((GUI_CreateMenu *)m_Layers[Create])->SetMapName(m_MapNames[m_CurrentMapSelected]);
                m_Layers[Create]->SetControlText(GUI_CreateMenu::UserName, Settings::GetNickName());
            }
            break;
        case GUI_MainMenu::ConnectGame:
            {
                m_ActiveMenu = Connect;
                m_NeedRepaint = true;
                m_Layers[Connect]->SetControlText(GUI_ConnectMenu::ServerAddress, Settings::GetServerAddress());
                m_Layers[Connect]->SetControlText(GUI_ConnectMenu::UserName, Settings::GetNickName());
            }
            break;
        case GUI_MainMenu::Settings:
            {
                m_ActiveMenu = Settings;
                ScreenMode = m_GUI->GetCurrentScreenMode();
                Resolution = m_GUI->GetResolution(ScreenMode);
                sprintf(Buffer, "%dx%d", Resolution->w, Resolution->h);
                const char * res = Buffer;
                m_Layers[Settings]->SetLabelText(GUI_SettingsMenu::ResolutionValue, res);

                FullscreenMode = m_GUI->GetCurrentFullscreenMode();
                m_Layers[Settings]->SetLabelText(GUI_SettingsMenu::FullscreenModeValue, (FullscreenMode) ? ("Fullscreen") : ("Windowed"));
                m_NeedRepaint = true;
            }
            break;
        case GUI_MainMenu::Exit:
            m_GUI->SwitchToScreen(GUI::Exit);
            break;
        default:
            break;
        }
        break;
    case Settings:
        switch(_result)
        {
        case -2:
            m_NeedRepaint = false;
            break;
        case -1:
            break;
        case GUI_SettingsMenu::NextScreenResolution:
            {
                ScreenMode--;
                Resolution = m_GUI->GetResolution(ScreenMode);

                sprintf(Buffer, "%dx%d", Resolution->w, Resolution->h);
 
                const char * res = Buffer;
                m_Layers[Settings]->SetLabelText(GUI_SettingsMenu::ResolutionValue, res);
            }
            break;
        case GUI_SettingsMenu::PreviousScreenResolution:
            {
                ScreenMode++;
                Resolution = m_GUI->GetResolution(ScreenMode);
                sprintf(Buffer, "%dx%d", Resolution->w, Resolution->h);
                const char * res = Buffer;
                m_Layers[Settings]->SetLabelText(GUI_SettingsMenu::ResolutionValue, res);
            }
            break;
        case GUI_SettingsMenu::PreviousFullscreenMode:
        case GUI_SettingsMenu::NextFullscreenMode:
            {
                FullscreenMode = !FullscreenMode;
                m_Layers[Settings]->SetLabelText(GUI_SettingsMenu::FullscreenModeValue, (FullscreenMode) ? ("Fullscreen") : ("Windowed"));
            }
            break;
        case GUI_SettingsMenu::Apply:
            Settings::SetResolution(m_GUI->GetResolution(ScreenMode));
            Settings::SetFullscreenMode(FullscreenMode);
            m_GUI->Resize(ScreenMode, FullscreenMode);
            m_ActiveMenu = Main;
            m_NeedRepaint = true;
            break;
        case GUI_SettingsMenu::Cancel:
            m_ActiveMenu = Main;
            m_NeedRepaint = true;
            break;
        default:
            break;
        }
        break;
    case Connect:
        switch(_result)
        {
        case -2:
            m_NeedRepaint = false;
            break;
        case -1:
            break;
        case GUI_ConnectMenu::Connect:

            Settings::SetServerAddress(m_Layers[Connect]->GetControlText(GUI_ConnectMenu::ServerAddress));
            Settings::SetNickName(m_Layers[Connect]->GetControlText(GUI_ConnectMenu::UserName));

            m_GUI->SwitchToScreen(GUI::Play);
            break;
        case GUI_ConnectMenu::Cancel:
            m_ActiveMenu = Main;
            m_NeedRepaint = true;
            break;
        default:
            break;
        }
        break;
    case Create:
        switch(_result)
        {
        case -2:
            m_NeedRepaint = false;
            break;
        case -1:
            break;
        case GUI_CreateMenu::NextMap:
            {
                m_CurrentMapSelected = (m_CurrentMapSelected + 1) % m_MapNames.size();
                ((GUI_CreateMenu *)m_Layers[Create])->SetMapName(m_MapNames[m_CurrentMapSelected]);

            }
            break;
        case GUI_CreateMenu::PreviousMap:
            {
                m_CurrentMapSelected --;
                if (m_CurrentMapSelected < 0) m_CurrentMapSelected += m_MapNames.size();
                ((GUI_CreateMenu *)m_Layers[Create])->SetMapName(m_MapNames[m_CurrentMapSelected]);
            }
            break;
        case GUI_CreateMenu::Create:
            Settings::SetServerAddress(((GUI_ConnectMenu *)m_Layers[Connect])->GetControlValue(GUI_ConnectMenu::ServerAddress));
            Settings::SetNickName(((GUI_ConnectMenu *)m_Layers[Connect])->GetControlValue(GUI_ConnectMenu::UserName));
            
            spawnl(P_NOWAIT, ".\\server.exe", ".\\server.exe", m_MapNames[m_CurrentMapSelected].c_str(), NULL);

            m_GUI->SwitchToScreen(GUI::Play);
            break;
        case GUI_CreateMenu::Cancel:
            m_ActiveMenu = Main;
            m_NeedRepaint = true;
            break;
        default:
            break;
        }
        break;
    }
}


//////////////////////////////////////////////////////////////////////////


void GUI_MenuScreen::OnKeyChanged(Input* _input)
{
    Input::Key key = _input->GetKey(); 
    if ((key.m_State == Input::RELEASED) || (key.m_State == Input::MOUSE_RELEASED))
    {
        switch (key.m_Code)
        {
        case Input::EXIT:
            m_GUI->SwitchToScreen(GUI::Exit);
            break;

        default:
            //assert(0);
            break;
        }
    }

    ProcessInputResult(m_Layers[m_ActiveMenu]->OnKeyChanged(_input));
}


//////////////////////////////////////////////////////////////////////////


void GUI_MenuScreen::OnMousePositionChanged(Input* _input)
{
    ProcessInputResult(m_Layers[m_ActiveMenu]->OnMousePositionChanged(_input));
}


//////////////////////////////////////////////////////////////////////////
